<?php

/***  DOCUMENTATION LAYER

Bafflegate Function Library

Last Update: Aug 2007
Author: Tom at klenwell@gmail.com

FUNCTIONS
  CLIENT LOCATION (ip/host/proxy)
  get_client_ip()
  get_hostname_by_ip($client_ip) 
  get_client_ip_simple()
  get_client_ip_pphlogger()
  get_proxy()
  extract_first_ip($string)
  is_valid_ip($ip)
  
  SITE INFO
  get_visited_url()
  
  write_file($content, $fpath, $overwrite=1)  


NOTES
  some common function used in bafflegate project -- most of these will
  eventually be incorporated into a class
  
  on issue of getting the *real* visitor ip, this is as definitive a discussion
  as I could find: http://php.net/manual/en/function.getenv.php

______________________________________________________________________________*/


// get ip
// source: http://groups.google.com/group/comp.lang.php/msg/02153fb3ddb8a0eb
// see also pphlogger functions.lib.php: get_real_IP()
/*____________________________________________________________________________*/
function get_client_ip() 
{
  $ip = '';
  
  // first we try HTTP_CLIENT_IP
  if ( !empty($_SERVER['HTTP_CLIENT_IP']) )
  {
    $ip = extract_first_ip($_SERVER['HTTP_CLIENT_IP']);
  }
  
  // then HTTP_X_FORWARDED
  elseif ( !empty($_SERVER['HTTP_X_FORWARDED']) )
  {
    $ip = extract_first_ip($_SERVER['HTTP_X_FORWARDED']);
  }
  
  // then HTTP_X_FORWARDED_FOR
  elseif ( !empty($_SERVER['HTTP_X_FORWARDED_FOR']) )
  {
    $ip = extract_first_ip($_SERVER['HTTP_X_FORWARDED_FOR']);
  }
  
  // default: REMOTE_ADDR
  if ( !is_valid_ip($ip) )
  {
    $ip = get_client_ip_simple();
  }

  return $ip;
} 
/*____________________________________________________________________________*/


// get hostname
/*____________________________________________________________________________*/
function get_hostname_by_ip($ip) 
{
  $hostname = '';
  $hostname = @getHostByAddr($ip);
  return $hostname;
} 
/*____________________________________________________________________________*/


// get ip address (the simple way)
/*____________________________________________________________________________*/
function get_client_ip_simple() 
{
  $ip = '';
  if ( !empty($_SERVER['REMOTE_ADDR']) ) $ip = $_SERVER['REMOTE_ADDR'];
  return $ip;
} 
/*____________________________________________________________________________*/


// get ip (old pphlogger method)
// source: pphlogger functions.lib.php
/*____________________________________________________________________________*/
function get_client_ip_pphlogger() 
{
  $ip = '';
  
  // Apache must be set up to do hostname lookups
  // why is this any better?
  if ( !empty($_SERVER['REMOTE_HOST']) ) 
  {
    $ip = extract_first_ip($_SERVER['REMOTE_HOST']);
  }
  
  if ( empty($ip) )
  {
    $ip = $_SERVER['REMOTE_ADDR'];
  }
	
	return $ip;
} 
/*____________________________________________________________________________*/


// get proxy (the simple way)
// see pphlogger.php
/*____________________________________________________________________________*/
function get_proxy() 
{
  $proxy = '';
  
  if ( empty($_SERVER['HTTP_VIA']) ) return false;
  
  $proxy = trim(addslashes(urldecode(strstr($_SERVER['HTTP_VIA'],' '))));
  return $proxy;
} 
/*____________________________________________________________________________*/


// extract ip from remote host
// source: pphlogger functions.lib.php
/*____________________________________________________________________________*/
function extract_first_ip($string) 
{
  $ip = '';
  $MATCH = array();
  $regex = '^([0-9]{1,3}\.){3,3}[0-9]{1,3}';
  
  if ( ereg($regex, $string, $_MATCH) )
  {
    $ip = $_MATCH[0];
  }
  
  return $ip;
} 
/*____________________________________________________________________________*/


// is the ip valid?
// source: http://www.teratechnologies.net/stevekamerman/index.php?entry=entry060606-220921
/*____________________________________________________________________________*/
function is_valid_ip($ip) 
{
// *** DATA
  
  // return
  $is_valid = 0;
  
  // reserved IPs
  $_RESERVED_IP = array
  (
    array('0.0.0.0','2.255.255.255'),
    array('10.0.0.0','10.255.255.255'),
    array('127.0.0.0','127.255.255.255'),
    array('169.254.0.0','169.254.255.255'),
    array('172.16.0.0','172.31.255.255'),
    array('192.0.2.0','192.0.2.255'),
    array('192.168.0.0','192.168.255.255'),
    array('255.255.255.0','255.255.255.255')
  );

  
// *** MANIPULATE

  // sanity check
  if ( empty($ip) || ip2long($ip) == -1 ) return 0;

  // check for reserved IP
  foreach ( $_RESERVED_IP as $_LIMIT )
  {
    $_min = ip2long($_LIMIT[0]);
    $_max = ip2long($_LIMIT[1]);
  
    // check range
    if ( (ip2long($ip) >= $_min) && (ip2long($ip) <= $_max) ) return 0;
  }
  
  // still here?  must be valid
  $is_valid = 1;


// *** RETURN

  return $is_valid;
}
/*____________________________________________________________________________*/


// get the url for the page whose visit we want to count
/*____________________________________________________________________________*/
function get_visited_url() 
{
  $visited_url = '';
  
  // first try HTTP_REFERER as this should be the site hosting the tracker
  if ( !empty($_SERVER['HTTP_REFERER']) )
  {
    $visited_url = $_SERVER['HTTP_REFERER'];
  }
  
  // fallback, $_GET['url'] (if set)
  elseif ( !empty($_GET['url']) )
  {
    $visited_url = $_GET['url'];
  }
  
  return $visited_url;
} 
/*____________________________________________________________________________*/



// get base domain (domain.tld)
/*____________________________________________________________________________*/
function get_base_domain($url) 
{
  $debug = 0;  
  $base_domain = '';
  
  // generic tlds (source: http://en.wikipedia.org/wiki/Generic_top-level_domain)
  $G_TLD = array(
    'biz','com','edu','gov','info','int','mil','name','net','org',
    'aero','asia','cat','coop','jobs','mobi','museum','pro','tel','travel',
    'arpa','root',
    'berlin','bzh','cym','gal','geo','kid','kids','lat','mail','nyc','post','sco','web','xxx',
    'nato',
    'example','invalid','localhost','test',
    'bitnet','csnet','ip','local','onion','uucp',
    'co'   // note: not technically, but used in things like co.uk
  );
  
  // country tlds (source: http://en.wikipedia.org/wiki/Country_code_top-level_domain)
  $C_TLD = array(
    // active
    'ac','ad','ae','af','ag','ai','al','am','an','ao','aq','ar','as','at','au','aw','ax','az',
    'ba','bb','bd','be','bf','bg','bh','bi','bj','bm','bn','bo','br','bs','bt','bw','by','bz',
    'ca','cc','cd','cf','cg','ch','ci','ck','cl','cm','cn','co','cr','cu','cv','cx','cy','cz',
    'de','dj','dk','dm','do','dz','ec','ee','eg','er','es','et','eu','fi','fj','fk','fm','fo',
    'fr','ga','gd','ge','gf','gg','gh','gi','gl','gm','gn','gp','gq','gr','gs','gt','gu','gw',
    'gy','hk','hm','hn','hr','ht','hu','id','ie','il','im','in','io','iq','ir','is','it','je',
    'jm','jo','jp','ke','kg','kh','ki','km','kn','kr','kw','ky','kz','la','lb','lc','li','lk',
    'lr','ls','lt','lu','lv','ly','ma','mc','md','mg','mh','mk','ml','mm','mn','mo','mp','mq',
    'mr','ms','mt','mu','mv','mw','mx','my','mz','na','nc','ne','nf','ng','ni','nl','no','np',
    'nr','nu','nz','om','pa','pe','pf','pg','ph','pk','pl','pn','pr','ps','pt','pw','py','qa',
    're','ro','ru','rw','sa','sb','sc','sd','se','sg','sh','si','sk','sl','sm','sn','sr','st',
    'sv','sy','sz','tc','td','tf','tg','th','tj','tk','tl','tm','tn','to','tr','tt','tv','tw',
    'tz','ua','ug','uk','us','uy','uz','va','vc','ve','vg','vi','vn','vu','wf','ws','ye','yu',
    'za','zm','zw',
    // inactive
    'eh','kp','me','rs','um','bv','gb','pm','sj','so','yt','su','tp','bu','cs','dd','zr'
    );
  
  
  // get domain
  if ( !$full_domain = get_url_domain($url) )
  {
    return $base_domain;
  }
  
  // now the fun
  
    // break up domain, reverse
    $DOMAIN = explode('.', $full_domain);
    if ( $debug ) print_r($DOMAIN);
    $DOMAIN = array_reverse($DOMAIN);
    if ( $debug ) print_r($DOMAIN);
    
    // first check for ip address
    if ( count($DOMAIN) == 4 && is_numeric($DOMAIN[0]) && is_numeric($DOMAIN[3]) )
    {
      return $full_domain;
    }
    
    // if only 2 domain parts, that must be our domain
    if ( count($DOMAIN) <= 2 ) return $full_domain;
    
    /* 
      finally, with 3+ domain parts: obviously D0 is tld 
      now, if D0 = ctld and D1 = gtld, we might have something like com.uk
      so, if D0 = ctld && D1 = gtld && D2 != 'www', domain = D2.D1.D0
      else if D0 = ctld && D1 = gtld && D2 == 'www', domain = D1.D0
      else domain = D1.D0
      these rules are simplified below 
    */
    if ( in_array($DOMAIN[0], $C_TLD) && in_array($DOMAIN[1], $G_TLD) && $DOMAIN[2] != 'www' )
    {
      $full_domain = $DOMAIN[2] . '.' . $DOMAIN[1] . '.' . $DOMAIN[0];
    }
    else
    {
      $full_domain = $DOMAIN[1] . '.' . $DOMAIN[0];;
    }
  
  // did we succeed?  
  return $full_domain;
} 
/*____________________________________________________________________________*/


// get domain from url
/*____________________________________________________________________________*/
function get_url_domain($url) 
{
  $domain = '';
  
  $_URL = parse_url($url);
  
  // sanity check
  if ( empty($_URL) || empty($_URL['host']) )
  {
    $domain = '';
  }
  else
  {
    $domain = $_URL['host'];
  }
  
  return $domain;
} 
/*____________________________________________________________________________*/


// get subdomain
/*____________________________________________________________________________*/
function get_subdomain($url) 
{
  $subdomain = '';
  if ( !$full_domain = get_url_domain($url) ) return $subdomain;
  if ( !$base_domain = get_base_domain($url) ) return $subdomain;
  $subdomain = str_replace($base_domain, '', $full_domain);
  if ( substr($subdomain,-1) == '.' ) $subdomain = substr($subdomain,0,strlen($subdomain)-1);
  return $subdomain;
} 
/*____________________________________________________________________________*/


// get query string
/*____________________________________________________________________________*/
function get_qstring($url) 
{
  $qstring = '';
  $delim_pos = strpos($url, '?');
  if ( $delim_pos === FALSE ) return ''; 
  $qstring = substr($url, $delim_pos + 1);
  
  // if query strings are separated by colons, change them to '&'
  if ( strstr($qstring,';') && !strstr($qstring,'&') ) $qstring = str_replace(';','&',$qstring);
  
  return $qstring;
} 
/*____________________________________________________________________________*/


// write file
/*____________________________________________________________________________*/
function write_file($content, $fpath, $overwrite=1) 
{
// *** DATA

	// write modes
	$_MODE = array
	(
		'rw_start' => 'w+',		// read/write, pointer at start of file
		'w_start' => 'w',			// write, start
		'w_end' => 'a',				// write, end
	);
	
	// internal
	$_mode = $_MODE['rw_start'];

	// Return
	$is_written = 0;


// *** MANIPULATE

	// set mode
	$_mode = ( $overwrite ) ? $_MODE['w_start'] : $_MODE['w_end'] ;

	// open file (with lock?)
	if ( !$_handle = fopen($fpath, $_mode) )
	{
		trigger_error("unable to open file for writing [$fpath]", E_USER_WARNING);
		return 0;
	}
	
	// write
	if ( fwrite($_handle, $content) === FALSE )
	{
		trigger_error("unable to write to file [$fpath]", E_USER_WARNING);
		$is_written = 0;
	}
	else
	{
		$is_written = 1;
	}    
		
	// close file
	fclose($_handle);

// *** RETURN

	return $is_written;

} // end Fx
/*____________________________________________________________________________*/


// Testbed
/*____________________________________________________________________________*/

if ( 0 )
{
	// test code here
  $TESTURL[] = 'http://127.0.0.1'; 
  $TESTURL[] = 'http://www.examplesite.com.pk'; 
  $TESTURL[] = 'http://domain.tv.com';
  $TESTURL[] = 'http://domain.com.tv';
  $TESTURL[] = 'http://domain.tv';
  $TESTURL[] = 'http://domain.com';
  $TESTURL[] = 'http://secure.email.website.co.uk'; 
  $TESTURL[] = 'http://username:password@this.is.a.worst.shortly.subdomain.thisIsMyMainWebsite.com.cl'; 
  
  foreach ( $TESTURL as $url )
  {
    echo $url . ' -> ' . get_subdomain($url) . ' + ' . get_base_domain($url) . '<br>';
  }
  
  $qtest = 'http://abclocal.go.com/kgo/story?section=local&id=5608335';
  echo $qtest . ' -> ' . get_qstring($qtest);
}

/*____________________________________________________________________________*/

?>
